//
//  OwlDocument.m
//  Owl
//
//  Created by Tianzhou on 09-1-10.
//  Copyright Tianzhou Software Inc. 2009 . All rights reserved.
//

#import "OwlDocument.h"
#import "Owl.h"
#import "OwlPreferenceKeys.h"
#import "OwlWindowController.h"
#import "OwlSourceListViewController.h"
#import "ChildNode.h"
#import "OwlSupport.h"
#import "GTMScriptRunner.h"

NSString *const kDefaultFileName = @"Owl";

@interface OwlDocument(Private_Method)

//- (BOOL)calculateLineCountForFile:(NSString *)path
//                         atFolder:(NSString *)folderPath;
@end



static NSString *const kPrefsToWatch[] = 
{
    kOwlSuffixListKey
};


@implementation OwlDocument



+ (void)registerDefaults
{
	NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
	NSDictionary *documentDefaults =
	    [NSDictionary dictionaryWithObjectsAndKeys:
		 @".m;;.h;.mm;;",
	     kOwlSuffixListKey,
	     nil];
	[defaults registerDefaults:documentDefaults];
}

- (NSString *)valuesKey:(NSString*)key
{
	return [NSString stringWithFormat:@"values.%@", key];
}

// -------------------------------------------------------------------------------
//	setContents:newContents
// -------------------------------------------------------------------------------
- (void)setContents:(NSArray *)newContents
{
	if (contents_ != newContents)
	{
		[contents_ release];
		contents_ = [[NSMutableArray alloc] initWithArray:newContents];
	}
}

// -------------------------------------------------------------------------------
//	contents:
// -------------------------------------------------------------------------------
- (NSArray *)contents
{
	NSLog(@"contents");
	return contents_;
}

// -------------------------------------------------------------------------------
//	setSelectedContents:newContents
// -------------------------------------------------------------------------------
//- (void)setSelectedContents:(NSArray *)newContents
//{
//	if (contents_ != newContents)
//	{
//		[contents_ release];
//		contents_ = [[NSMutableArray alloc] initWithArray:newContents];
//	}
//}

- (ChildNode *)selectedNode
{
	return selectedNode_;
}

- (void)setSelectedNode:(ChildNode *)newNode
{
	selectedNode_ = newNode;
}

- (id)init
{
    self = [super init];
    if (self) {
    
        // Add your subclass-specific initialization here.
        // If an error occurs here, send a [self release] message and return nil.
		contents_ = [[NSMutableArray alloc] init];
    
    }
    return self;
}

- (void)awakeFromNib
{
	NSLog(@"awakeFromNib");
	NSUserDefaultsController *defaults = [NSUserDefaultsController sharedUserDefaultsController];
	for (size_t i = 0; i < sizeof(kPrefsToWatch) / sizeof(NSString*); ++i)
	{
		[defaults addObserver:self 
				   forKeyPath:[self valuesKey:kPrefsToWatch[i]]
					  options:NSKeyValueObservingOptionNew
					  context:nil];
	}
}

- (void)dealloc
{
	NSLog(@"dealloc");
	NSUserDefaultsController *defaults = [NSUserDefaultsController sharedUserDefaultsController];
	for (size_t i = 0; i < sizeof(kPrefsToWatch) / sizeof(NSString*); ++i)
	{
		[defaults removeObserver:self 
					  forKeyPath:[self valuesKey:kPrefsToWatch[i]]];
	}
	[contents_ release];
	[super dealloc];
}

- (void)makeWindowControllers
{
	mainWindowController_ = [OwlWindowController defaultWindowController];
	[self addWindowController:mainWindowController_];
}

- (void)windowControllerDidLoadNib:(NSWindowController *) aController
{
    [super windowControllerDidLoadNib:aController];
	
	// Change the window tile from "Untitled" to the prefered name
	// TODO: Any better way to do it?
	[self setFileName:kDefaultFileName];
//	ChildNode *theNode = [[ChildNode alloc] init];
//	[theNode setNodeTitle:@"test"];
//	OwlSourceListViewController *theC = [(OwlWindowController *)mainWindowController_ sourceListViewController];
//	[[(OwlWindowController *)mainWindowController_ sourceListViewController] performAddChild:theNode];
//	[theNode release];
    // Add any code here that needs to be executed once the windowController has loaded the document's window.
}

- (NSData *)dataOfType:(NSString *)typeName error:(NSError **)outError
{
    // Insert code here to write your document to data of the specified type. If the given outError != NULL, ensure that you set *outError when returning nil.

    // You can also choose to override -fileWrapperOfType:error:, -writeToURL:ofType:error:, or -writeToURL:ofType:forSaveOperation:originalContentsURL:error: instead.

    // For applications targeted for Panther or earlier systems, you should use the deprecated API -dataRepresentationOfType:. In this case you can also choose to override -fileWrapperRepresentationOfType: or -writeToFile:ofType: instead.

    if ( outError != NULL ) {
		*outError = [NSError errorWithDomain:NSOSStatusErrorDomain code:unimpErr userInfo:NULL];
	}
	return nil;
}

- (BOOL)readFromFileWrapper:(NSFileWrapper *)fileWrapper
                     ofType:(NSString *)typeName
                      error:(NSError **)outError
{
	NSLog(@"read from file wrapper");
	// [fileWrapper filename] doesn't include the full path
	//NSString *path = [self fileName];
//	int totalLines = [OwlDocument calculateLineCountForWrapper:fileWrapper
//											withAbsolutePath:path];
//	NSLog(@"Total line is %d under %@", totalLines, path);
	
	return YES;
}

- (BOOL)readFromData:(NSData *)data ofType:(NSString *)typeName error:(NSError **)outError
{
    // Insert code here to read your document from the given data of the specified type.  If the given outError != NULL, ensure that you set *outError when returning NO.

    // You can also choose to override -readFromFileWrapper:ofType:error: or -readFromURL:ofType:error: instead. 
    
    // For applications targeted for Panther or earlier systems, you should use the deprecated API -loadDataRepresentation:ofType. In this case you can also choose to override -readFromFile:ofType: or -loadFileWrapperRepresentation:ofType: instead.
    
    if ( outError != NULL ) {
		*outError = [NSError errorWithDomain:NSOSStatusErrorDomain code:unimpErr userInfo:NULL];
	}
    return YES;
}

- (void)observeValueForKeyPath:(NSString *)keyPath 
                      ofObject:(id)object 
                        change:(NSDictionary *)change 
                       context:(void *)context
{
	if ([object isEqualTo:[NSUserDefaultsController sharedUserDefaultsController]])
	{
		if ([keyPath isEqualToString:[self valuesKey:kOwlSuffixListKey]])
		{
			NSString *path = [self fileName];
			NSFileWrapper *fileWrapper = [[NSFileWrapper alloc] initWithPath:path];
			[OwlDocument calculateLineCountForWrapper:fileWrapper
									 withAbsolutePath:path];
		}
	}
}

#pragma mark Private_Method
+ (int)calculateLineCountForWrapper:(NSFileWrapper *)fileWrapper
                    withAbsolutePath:(NSString *)path
{
	if ([fileWrapper isDirectory])
	{
		return [self gatherWCDataUnderPath:path];
	}
	// TODO: deal with the single file case..
	else if ([fileWrapper isRegularFile])
	{
		//return [OwlDocument calculateLineCountForFile:path atFolder:nil];
	}
	return 0;
}

//+ (int)gatherWCDataUnderPath:(NSString *)path
//{
//	NSLog(@"root folder name:%@",path);
//
//	int i;
//	int totalLines = 0;
//	NSArray *allFilePaths = [OwlSupport interestedFilesUnderPath:path];
//	for (i = 0; i < [allFilePaths count]; ++i)
//	{
//		totalLines += [OwlDocument calculateLineCountForFile:[allFilePaths objectAtIndex:i]
//													atFolder:path];
//	}
//	return totalLines;
//}

+ (int)calculateLineCountForFile:(NSString *)path
                         atFolder:(NSString *)folderPath
{
	NSLog(@"file full path name:%@",path);
	GTMScriptRunner *runner = [GTMScriptRunner runnerWithBash];
	if (!runner)
	{
		NSLog(@"can not create the script runner!");
		return 0;
	}
	
	// Another way to do it is to use @"cd %@ && wc -l %@"
	NSString *bashCmd = [NSString stringWithFormat:@"wc -l %@/%@",folderPath,path];
	NSString *stdErr = nil;
	NSString *stdOut = [runner run:bashCmd standardError:&stdErr];
	NSLog(@"err:%@",stdErr);
	NSLog(@"out:%@",stdOut);
	
	if (!stdErr)
	{
		NSRange theRange = [stdOut rangeOfString:@" "];
		return [[stdOut substringToIndex:theRange.location] intValue];
	}
	else
	{
		NSLog(stdErr);
	}
	
	return 0;
}

#pragma mark OwlSourceListViewProtocol

- (void)respondToSourceListNewSelection:(id)newSelection
{
	selectedNode_ = newSelection;
//	if (isTableViewAdded_)
//	{ 
//		if ([tableViewController_ conformsToProtocol:@protocol(OwlSourceListViewProtocol)])
//		{
//			[tableViewController_ respondToSourceListNewSelection:newSelection];
//		}
//	}
}
//- (IBAction)importProject:(id)sender
//{
//	NSLog(@"import Project:%@",[[mainWindowController_ window] description]);
//	
//}



@end
